#include "UI.h"
#include "XLand.h"

using namespace ll::form;

/*
 * 显示领地主页
*/
void UI::main(Player *player, string const& title, string const& content) {
    SimpleForm element(title, content);
    auto langCode = XUtils::getPlayerLangCode(*player);
    string buts[] = {
        (string)i18n.get("add_land" , langCode),
        (string)i18n.get("land_perm", langCode),
        (string)i18n.get("land_mess", langCode),
        (string)i18n.get("news_mess", langCode),
        (string)i18n.get("send_mess", langCode),
        (string)i18n.get("belong"   , langCode),
        (string)i18n.get("go_land"  , langCode)
    };
    for(auto& item : buts) element.appendButton(item);
    element.sendTo(*player, [](Player& player, int index, FormCancelReason){
        switch (index) {
            case 0:  addLand(&player  ); break;
            case 1: listLand(player, 0); break;
            case 2: listLand(player, 1); break;
            case 3:  messGui(player   ); break;
            case 4: formMess(player   ); break;
            case 5: listDate(player   ); break;
            case 6: listLand(player, 2); break;
            default: break;
        }
    });
}
void UI::addLand(Player* player, string const& title) {
    SimpleForm element(title);
    auto langCode = XUtils::getPlayerLangCode(*player);
    string buts[] = {
        (string)i18n.get("occupy_swich", langCode),
        (string)i18n.get("buy_land"    , langCode)
    };
    for(auto& item : buts) element.appendButton(item);
    element.sendTo(*player,[](Player& player, int index, FormCancelReason){
        switch (index) {
            case 0: XPacket::playerRunCommand(player,"xland set_pt"); break;
            case 1: XPacket::playerRunCommand(player,"xland buy")   ; break;
        }
    });
}
void UI::listLand(Player& player, int index, string const& title) {
    SimpleForm element(title);
    auto list     = XLand::listLand(player.getUuid());
    auto langCode = XUtils::getPlayerLangCode(player);
    if(list->size() < 1) element.appendButton((string)i18n.get("no_land", langCode));
    for(auto& item : *list) {
        const auto id    = item.id;
        const auto name  = item.getLandName();
        element.appendButton(fmt::format("{} {}",id,name),[item,id,index](Player& player){
            switch (index) {
                case 0: mgtLand(player,id); break;
                case 1: setLand(player,id); break;
                case 2: item.tpLand(player); break;
            }
        });
    }
    element.sendTo(player);
}
void UI::mgtLand(Player& player, const long id, mce::UUID uuid, string const& title) {
    auto level    = ll::service::getLevel();
    auto langCode = XUtils::getPlayerLangCode(player);
    CustomForm     element(title);
    vector<string> playerNames = {
        (string)i18n.get("land_default", langCode)
    };
    map<string, mce::UUID> players = {
        {(string)i18n.get("land_default", langCode), 0}
    };
    for(const auto& item : PlayerDate::playerDate) {
        auto name = level->getPlayer(item.first)->getName();
        players[name] = item.first;
        playerNames.push_back(name);
    }
    auto name = uuid == 0 ? (string)i18n.get("land_default", langCode) : level->getPlayer(uuid)->getName();
    LandPerm playerLandPerm(id, uuid);
    element.appendLabel(papilio::format(i18n.get("GUI_mgtLand_base", langCode), name, playerLandPerm.getJson().dump(2)));
    // element.appendInput("playerRealName", "玩家真实名，不填写即修改领地默认权限");
    element.appendDropdown("playerName", (string)i18n.get("player_name"  , langCode), playerNames                );
    element.appendToggle("placeBlock"  , (string)i18n.get("put_block"    , langCode), playerLandPerm.placeBlock  );
    element.appendToggle("destroyBlock", (string)i18n.get("destory_block", langCode), playerLandPerm.destroyBlock);
    element.appendToggle("pickUpItem"  , (string)i18n.get("pick_up_item" , langCode), playerLandPerm.pickUpItem  );
    element.appendToggle("playerAttac" , (string)i18n.get("player_attack", langCode), playerLandPerm.playerAttac );
    element.appendDropdown("useItems"  , (string)i18n.get("add_use_item" , langCode), config.useItems            );
    element.appendDropdown("useBlocks" , (string)i18n.get("add_use_block", langCode), config.useBlocks           );
    element.appendDropdown("useEntitys", (string)i18n.get("add_use_actor", langCode), config.useEntitys          );
    element.appendToggle("sele"        , (string)i18n.get("if_end_set"   , langCode)                             );
    element.sendTo(player,[playerLandPerm, players, id](Player& player, CustomFormResult const& form, FormCancelReason a) {
        if(a.has_value()) return;
        LandPerm perm = playerLandPerm;
        map<string, mce::UUID> mPlayers = players;
        perm.placeBlock   = get<unsigned long long>(form->at("placeBlock"  ));
        perm.destroyBlock = get<unsigned long long>(form->at("destroyBlock"));
        perm.pickUpItem   = get<unsigned long long>(form->at("pickUpItem"  ));
        perm.playerAttac  = get<unsigned long long>(form->at("playerAttac" ));
        perm.useItems  .push_back( config.itemRealName[get<string>(form->at("useItems"   ))] );
        perm.useBlocks .push_back( config.itemRealName[get<string>(form->at("useBlocks"  ))] );
        perm.useEntitys.push_back( config.itemRealName[get<string>(form->at("useEntitys" ))] );
        auto name = get<string>(form->at("playerName"));
        auto uuid = mPlayers[name];
        auto text = fmt::format("{} {}", name, XLand::setLand(id, perm.getJson(), uuid, 1));
        if(get<unsigned long long>(form->at("sele"))) TextPacket::createRawMessage(text).sendTo(player);
        else mgtLand(player, id, uuid);
    });
}
void UI::setLand(Player& player, const long id, string const& title) {
    CustomForm element(title);
    auto land     = XLand(id);
    auto langCode = XUtils::getPlayerLangCode(player);
    auto balance  = papilio::format(i18n.get("balance", langCode), land.balance);
    element.appendLabel(papilio::format(i18n.get("GUI_setLand_base", langCode), land.getLandName(), land.area, land.getOwnerName(), land.balance));
    element.appendInput("landName"   , (string)i18n.get("land_name"           , langCode), land.name, land.getLandName());
    element.appendInput("money"      , (string)i18n.get("top_up_money"        , langCode), balance                      );
    element.appendToggle("pENTERLand", (string)i18n.get("if_enter_land_prompt", langCode), land.pENTERLand              );
    element.appendToggle("pistonPush", (string)i18n.get("if_pistonPush"       , langCode), land.pistonPush              );
    element.appendToggle("explode"   , (string)i18n.get("if_explode"          , langCode), land.explode                 );
    element.appendToggle("liquidFlow", (string)i18n.get("if_liquidFlow"       , langCode), land.liquidFlow              );
    element.sendTo(player,[land, langCode](Player& player, CustomFormResult const& form, FormCancelReason a) {
        if(a.has_value()) return;
        XLand mland = land;
        mland.name       = get<string>(form->at("landName"));
        mland.pENTERLand = get<unsigned long long>(form->at("pENTERLand"));
        mland.pistonPush = get<unsigned long long>(form->at("pistonPush"));
        mland.explode    = get<unsigned long long>(form->at("explode"));
        mland.liquidFlow = get<unsigned long long>(form->at("liquidFlow"));
        auto    moneyStr = get<string>(form->at("money"));
        long long money  = 0;
        try {money = stoll(moneyStr);} catch(std::exception const &e) {}

        auto xuid = player.getXuid();
        REDUCE_MONEY(money) warningMess(player, papilio::format(i18n.get("balance_warning", langCode), money)); REDUCE_MONEY_END(money)
        mland.balance += money;
        string textRaw;
        switch (XLand::setLand(mland.id, mland.getJson(), player.getUuid(), 0)) {
            case  0: textRaw = i18n.get("set_success"  , langCode); break;
            case  1: textRaw = i18n.get("no_owner"     , langCode); break;
            case  2: textRaw = i18n.get("set_failure"  , langCode); break;
            default: textRaw = i18n.get("unknow_error" , langCode);
        }
        TextPacket::createRawMessage(textRaw).sendTo(player);
    });
}
void UI::listDate(Player& player, const string& title , const string& content) {
    SimpleForm element(title, content);
    auto lands    = XLand::getLand(player);
    auto langCode = XUtils::getPlayerLangCode(player);
    string where;
    if(lands.size() < 1) {
        lands = XLand::getLand(player, false); //不是领主
        where = fmt::format("AND form = '{}'",player.getUuid().asString());
    }
    for(const auto& i : lands) {
        auto mess = XLand::getMess(i,fmt::format("AND (type = 1 AND status = 2 {})",where));
        for(const auto& j : mess) element.appendButton(j.title, [j,langCode](Player& player){
            if(XLand::upDateMess(j.id,3)) TextPacket::createRawMessage(i18n.get("exit_land", langCode)).sendTo(player);
        });
    }
    element.sendTo(player);
}
void UI::messGui(Player& player, const string& title , const string& content ) {
    SimpleForm element(title, content);
    auto lands    = XLand::getLand(player);
    auto langCode = XUtils::getPlayerLangCode(player);
    int sum = 0;
    for(const auto& i : lands) {
        auto mess = XLand::getMess(i,"AND (status = 0 OR (type IN (0,2) AND status = 2) )");
        sum += mess.size();
        for(const auto& j : mess) element.appendButton(j.title, [j](Player& player){
            updateMess(player,j);
        });
    }
    if(sum < 1) element.appendButton((string)i18n.get("null", langCode));
    element.sendTo(player);
}
void UI::formMess(Player& player, const string& title) {
    CustomForm element(title);
    auto langCode = XUtils::getPlayerLangCode(player);
    element.appendDropdown("type", (string)i18n.get("mess_type", langCode), config.messType);
    element.appendInput("to"     , (string)i18n.get("send_to"  , langCode), (string)i18n.get("GUI_sendMess_input_to", langCode));
    element.appendInput("content", (string)i18n.get("content"  , langCode));
    element.sendTo(player,[langCode](Player& player, CustomFormResult const& form, FormCancelReason a){
        if(a.has_value()) return;
        auto to      = XLand::getLandId(get<string>(form->at("to")));
        if(!to) {warningMess(player, string(i18n.get("warning_no_land", langCode))); return;}
        auto land    = XLand(to);

        auto type    = config.itemRealType[get<string>(form->at("type"))];
        auto mform   = player.getUuid().asString();
        auto content = get<string>(form->at("content"));
        string title; 
        auto name    = player.getName();
        
        switch (type) {
            case 0: 
                title = papilio::format(i18n.get("message", langCode), name);
                break;
            case 1: {
                auto lands = XLand::getLand(player);
                if(lands.size() > 0) {warningMess(player, string(i18n.get("warning_is_owner", langCode))); return;}
                lands = XLand::getLand(player, false);
                if(!(lands.empty()) && land.owner != XLand(*lands.begin()).owner) {warningMess(player,string(i18n.get("warning_only_one_owner", langCode))); return;}
                try {
                    SQLite::Statement get{*XLand::db,fmt::format("SELECT `to` FROM mess WHERE type = 1 AND status = 0 AND form = '{}'", player.getUuid().asString())};
                    if(get.executeStep()) {warningMess(player,string(i18n.get("warning_check", langCode))); return;}
                    get.clearBindings();
                } catch (std::exception const &e) {cerr << "获取领地ID失败: " << e.what() << endl; return;}
                title = papilio::format("{}：{} -> {}：{}", i18n.get("ciziten", langCode), name, land.getLandName(), i18n.get("move_into", langCode));
                break;
            }
            default: 
                title = i18n.get("others", langCode);
                break;
        }
        if(XLand::formMess(XLand::Mess(0, mform, to, type, title, content ,0))) TextPacket::createRawMessage(i18n.get("send_mess_success", langCode)).sendTo(player);
    });
}
void UI::updateMess(Player& player, const XLand::Mess& mess) {
    string left("on"), right("yes");
    auto langCode = XUtils::getPlayerLangCode(player);
    switch (mess.type) {
        case 0: right = i18n.get("delete", langCode); left = i18n.get("reserve", langCode); break;
        case 1: right = i18n.get("refuse", langCode); left = i18n.get("agree"  , langCode); break;
    }
    ModalForm element(mess.title, mess.content,left,right);
    element.sendTo(player,[mess,left,langCode](Player& player, ModalFormResult select, FormCancelReason a){
        if(a.has_value()) return;
        auto status = (select.has_value() && (bool) select.value()) ? 2 : 1;
        if(mess.type == 2 && status == 1) {
            CustomForm element(string(i18n.get("GUI_settlement_title", langCode)));
            element.appendInput("money", string(i18n.get("settlement_amount", langCode)), papilio::format("> {}", mess.money), to_string(mess.money));
            element.sendTo(player,[mess,langCode](Player& player, CustomFormResult const& form, FormCancelReason a){
                if(a.has_value()) return;
                auto moneyStr = get<string>(form->at("money"));
                long long money = 100;
                try {money = stoll(moneyStr);} catch(std::exception const &e) {}
                if(money < mess.money) {warningMess(player,papilio::format(i18n.get("settlement_amount_insufficient", langCode), money)); return;}
                auto xuid = player.getXuid();
                REDUCE_MONEY(money) warningMess(player,papilio::format(i18n.get("balance_warning", langCode), money)); REDUCE_MONEY_END(money)
                if(XLand::upDateMess(mess.id, 1)) TextPacket::createRawMessage(i18n.get("settlement", langCode)).sendTo(player);
            });
            return;
        }
        if(XLand::upDateMess(mess.id, status)) TextPacket::createRawMessage("§a"+left).sendTo(player);
    });
}
void UI::warningMess(Player& player, const string& mess) {
    auto langCode = XUtils::getPlayerLangCode(player);
    ModalForm element(string(i18n.get("warning", langCode)), mess, string(i18n.get("close", langCode)), string(i18n.get("ok", langCode)));
    element.sendTo(player);
}